home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
FM Towns: Free Software Collection 4
/
FM Towns Free Software Collection 4 - Disc 1.iso
/
t_os
/
wstype
/
source
/
getfiles.c
< prev
next >
Wrap
C/C++ Source or Header
|
1991-10-18
|
8KB
|
319 lines
/*** [getfiles.c]
*
* ディレクトリ情報 関連 (C)ささがわ
*
* For GNU C Compiler (GCC) Version 1.39
*
***/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <dos.h>
#include "jstring.h"
#include "getfiles.h"
#define DEFAULT_BUF 30
#define ADD_BUF 50
#define STBUF_RETRY -1
#define STBUF_FATAL -2
typedef unsigned char Uchar;
static files *buf = NULL;
static int Set_buf(unsigned *);
static int Set_buf_again(int);
static void Sort_ext(files **, unsigned);
static void Sort_date(files **, unsigned);
static void Sort_name(files **, unsigned);
static void Sort_non(files **, unsigned);
static int cmp_dirornot(files **, files **);
static int cmp_base(files **, files **);
static int cmp_ext(files **, files **);
static int cmp_date(files **, files **);
static int cmp_name(files **, files **);
static int cmp_non(files **, files **);
static Uchar *get_extptr(Uchar *);
int Getfiles(int type, get_f *gf, int mode) {
int n;
unsigned n_file;
unsigned n_dir;
unsigned mf = DEFAULT_BUF;
files **ptr;
if (mode == 0) {
while ((n = Set_buf(&mf)) == STBUF_RETRY)
mf += ADD_BUF;
if (n == STBUF_FATAL) {
gf->pbuf = NULL;
return 1;
}
ptr = (files **)(buf + mf);
n_file = n;
n_dir = 0;
for (n = 0;n < mf;n++)
ptr[n] = buf + n;
} else {
ptr = gf->pbuf;
n_file = gf->nfiles;
n_dir = gf->ndir;
}
if (n_file == 0) {
gf->pbuf = ptr;
gf->nfiles = n_file;
gf->ndir = n_dir;
return 0;
}
/* ディレクトリ分離 */
qsort((void *)ptr, (size_t)n_file, (size_t)sizeof(files *), (int (*)(const void *, const void *))cmp_dirornot);
n = 0;
while (ptr[n]->attr & _A_SUBDIR && n < n_file)
n++;
n_dir = n;
switch (type) {
case GF_SEXT:
Sort_name(ptr, n_dir);
Sort_ext(ptr + n_dir, n_file - n_dir);
break;
case GF_SDATE:
Sort_date(ptr, n_dir);
Sort_date(ptr + n_dir, n_file - n_dir);
break;
case GF_SNAME:
Sort_name(ptr, n_dir);
Sort_name(ptr + n_dir, n_file - n_dir);
break;
default:
Sort_non(ptr, n_dir);
Sort_non(ptr + n_dir, n_file - n_dir);
break;
}
gf->pbuf = ptr;
gf->nfiles = n_file;
gf->ndir = n_dir;
return 0;
}
static int Set_buf(unsigned *cap_buf) {
int n_file;
unsigned atr = _A_NORMAL | _A_RDONLY | _A_SUBDIR | _A_ARCH;
struct find_t ft;
Gf_bufrel();
if ((buf = (files *)malloc(*cap_buf * (sizeof(files) + sizeof(files *)))) == NULL)
return STBUF_FATAL;
n_file = 0;
if (!_dos_findfirst("*.*", atr, &ft)) {
if (strcmp(".", ft.name) || !(ft.attrib & _A_SUBDIR)) {
strcpy((char *)buf[n_file].name, (const char *)ft.name);
buf[n_file].attr = ft.attrib;
buf[n_file].dt = ft.wr_date;
buf[n_file].tm = ft.wr_time;
buf[n_file].ord = n_file;
buf[n_file++].sz = ft.size;
}
if (n_file >= *cap_buf) {
if (Set_buf_again(*cap_buf))
return STBUF_RETRY;
*cap_buf += ADD_BUF;
}
while (!_dos_findnext(&ft)) {
if (strcmp(".", ft.name) || !(ft.attrib & _A_SUBDIR)) {
strcpy((char *)buf[n_file].name, (const char *)ft.name);
buf[n_file].attr = ft.attrib;
buf[n_file].dt = ft.wr_date;
buf[n_file].tm = ft.wr_time;
buf[n_file].ord = n_file;
buf[n_file++].sz = ft.size;
}
if (n_file >= *cap_buf) {
if (Set_buf_again(*cap_buf))
return STBUF_RETRY;
*cap_buf += ADD_BUF;
}
}
}
return n_file;
}
static int Set_buf_again(int n) {
files *buf2;
if ((buf2 = (files *)malloc((n + ADD_BUF) * (sizeof(files) + sizeof(files *)))) == NULL)
return -1;
memcpy(buf2, buf, n * (sizeof(files) + sizeof(files *)));
free(buf);
buf = buf2;
return 0;
}
/* 拡張子でソートし、そのうえでベース名でソートする関数 */
static void Sort_ext(files **ptr, unsigned no) {
int n = 0;
qsort((void *)ptr, (size_t)no, (size_t)sizeof(files *), (int (*)(const void *, const void *))cmp_ext);
while (n < no) {
Uchar *startptr;
unsigned start;
start = n;
startptr = get_extptr((Uchar *)ptr[n++]->name);
while (!strcmp((const char *)startptr, (const char *)get_extptr((Uchar *)(ptr[n]->name))) && n < no)
n++;
qsort((void *)(ptr + start), (size_t)(n - start), (size_t)sizeof(files *), (int (*)(const void *, const void *))cmp_base);
}
}
/* 作成日時でソートする関数 */
static void Sort_date(files **ptr, unsigned no) {
int n = 0;
qsort((void *)ptr, (size_t)no, (size_t)sizeof(files *), (int (*)(const void *, const void *))cmp_date);
while (n < no) {
int t, d, st;
st = n;
d = ptr[n]->dt; t = ptr[n++]->tm;
while (d == ptr[n]->dt && t == ptr[n]->tm && n < no)
n++;
qsort((void *)(ptr + st), (size_t)(n - st), (size_t)sizeof(files *), (int (*)(const void *, const void *))cmp_name);
}
}
/* ファイル名全体でソートする関数 */
static void Sort_name(files **ptr, unsigned no) {
qsort((void *)ptr, (size_t)no, (size_t)sizeof(files *), (int (*)(const void *, const void *))cmp_name);
}
/* ディレクトリ順にソートする関数 */
static void Sort_non(files **ptr, unsigned no) {
qsort((void *)ptr, (size_t)no, (size_t)sizeof(files *), (int (*)(const void *, const void *))cmp_non);
}
/* qsort関数用、サブディレクトリを識別する関数 */
static int cmp_dirornot(files **a, files **b) {
if ((*a)->attr & _A_SUBDIR && (*b)->attr & _A_SUBDIR)
return 0;
else if ((*a)->attr & _A_SUBDIR)
return -1;
else if ((*b)->attr & _A_SUBDIR)
return 1;
else
return 0;
}
/* qsort関数用、ベース名を比較する関数 */
static int cmp_base(files **a, files **b) {
Uchar c[13], d[13], *e;
strcpy((char *)c, (const char *)(*a)->name);
if ((e = jstrchr(c, '.')) != NULL)
*e = '\0';
strcpy((char *)d, (const char *)(*b)->name);
if ((e = jstrchr(d, '.')) != NULL)
*e = '\0';
return jstrcmp(c, d);
}
/* qsort関数用、拡張子を比較する関数 */
static int cmp_ext(files **a, files **b) {
return jstrcmp(get_extptr((Uchar *)(*a)->name), get_extptr((Uchar *)(*b)->name));
}
/* qsort関数用、作成日時を比較する関数 */
static int cmp_date(files **a, files **b) {
unsigned long d1, d2;
d1 = ((*a)->dt << 16) + (*a)->tm;
d2 = ((*b)->dt << 16) + (*b)->tm;
if (d1 > d2)
return 1;
else if (d1 < d2)
return -1;
else
return 0;
}
/* qsort関数用、ファイル名全体を比較する関数 */
static int cmp_name(files **a, files **b) {
if ((*a)->name[0] == '.' || (*b)->name[0] == '.')
return jstrcmp((Uchar *)(*a)->name, (Uchar *)(*b)->name);
else
return jstrcmp((Uchar *)(*a)->name, (Uchar *)(*b)->name);
}
/* qsort関数用、ディレクトリ順を比較する関数 */
static int cmp_non(files **a, files **b) {
if ((*a)->ord > (*b)->ord)
return 1;
else if ((*a)->ord < (*b)->ord)
return -1;
else
return 0;
}
/* 拡張子へのポインタを返す関数 */
static Uchar *get_extptr(Uchar *a) {
Uchar *b;
if ((b = jstrchr(a, '.')) == NULL)
return (a + strlen((char *)a));
else
return (b + 1);
}
void Gf_bufrel(void) {
free(buf);
buf = NULL;
}
int Split_fname(const char *f_name, unsigned atr, char *buf_base, char *buf_ext) {
int ret;
char *a;
static const char *exec_ext[] = {
".COM", ".EXE", ".EXP", ".BAT", ""
};
if ((a = strchr(f_name, '.')) == NULL) {
strcpy(buf_base, f_name);
buf_ext[0] = '\0';
} else {
buf_base[0] = '\0';
strncat(buf_base, f_name, a - f_name);
strcpy(buf_ext, a);
}
if (atr & _A_SUBDIR) {
ret = EX_DIR;
} else {
int i;
ret = EX_OTHER;
for (i = 0; exec_ext[i][0]; i++) {
if (!stricmp(buf_ext, exec_ext[i])) {
ret = EX_EXE;
break;
}
}
}
return ret;
}